
package cz.czu.pef.DataModelling;

import java.util.*;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import cz.czu.pef.DataModelling.utils.Lazy;

/**
 * This entity represents binding between RoleType and its MedicalExaminationType. This entity exists since the list of
 * MedicalExaminationType for given RoleType can be reused by more RoleTypes.
 * 
 * @author rstribrn
 *
 */
@Entity
@Table(name = "MED_EXAM_TYPES_FOR_ROLE_TYPES")
@Inheritance(strategy = InheritanceType.JOINED)
@ManagedBean(name="medicalExaminationTypeForRoleType")
@ViewScoped
@Component
@Scope(value="prototype")
public class MedicalExaminationTypeForRoleType extends IdPersistenceObject
{
	private static final long serialVersionUID = -4318181001409286326L;

	/*
	 * Entity attributes
	 */
	@ManyToOne(fetch=FetchType.EAGER, optional=true, targetEntity=MedicalExaminationType.class, cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
	@JoinTable(name="MAP_MET_FRT__MET")
	private MedicalExaminationType medicalExaminationType;

	/*
	 * Relations
	 */
	@ManyToMany(fetch = FetchType.LAZY, targetEntity = RoleType.class, mappedBy = "medExamTypesForRoleTypes") // no cascade!
	private Set<RoleType> roleTypes;

	private long periodicityInSeconds;

	protected MedicalExaminationTypeForRoleType()
	{
		super();
	}

	public MedicalExaminationTypeForRoleType(MedicalExaminationType medicalExaminationType, long periodicityInSeconds)
	{
		this.medicalExaminationType = medicalExaminationType;
		this.periodicityInSeconds = periodicityInSeconds;
	}

	@Lazy
	@Transactional(readOnly=true, propagation=Propagation.REQUIRED)
	public Set<RoleType> getRoleTypes()
	{
		return roleTypes;
	}
	@Lazy
	@Transactional(readOnly=true, propagation=Propagation.REQUIRED)
	public List<RoleType> getRoleTypesAsList()
	{
		return new ArrayList<RoleType>(getRoleTypes());
	}

	public void addRoleType(RoleType roleType)
	{
		if (this.roleTypes == null)
			this.roleTypes = new HashSet<RoleType>();
		this.roleTypes.add(roleType);
	}
	
	public long getPeriodicityInSeconds()
	{
		return periodicityInSeconds;
	}

	
	public void setPeriodicityInSeconds(long periodicityInSeconds)
	{
		this.periodicityInSeconds = periodicityInSeconds;
	}

	@Lazy
	@Transactional(readOnly=true, propagation=Propagation.REQUIRED)
	@Override
	public String toString()
	{
		StringBuilder builder = new StringBuilder();
		builder.append("MedicalExaminationTypeForRoleType [roleTypes=");
		builder.append(roleTypes);
		builder.append(", periodicityInSeconds=");
		builder.append(periodicityInSeconds);
		builder.append(", toString()=");
		builder.append(super.toString());
		builder.append("]");
		return builder.toString();
	}

	
	@Lazy
	@Transactional(readOnly=true, propagation=Propagation.REQUIRED)
	public MedicalExaminationType getMedicalExaminationType()
	{
		return medicalExaminationType;
	}

	/**
	 * Can be deleted after all related entities are deleted (no cascade).
	 */
	@Override
	public boolean canBeRemoved()
	{
		return getRoleTypes().size() == 0;
	}
}